package com.boarsoft.boar.deploy.event.biz;

import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.websocket.Session;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.boarsoft.boar.deploy.common.BuildContext;
import com.boarsoft.boar.deploy.entity.BuildPlanItem;
import com.boarsoft.boar.deploy.entity.DeployRecord;
import com.boarsoft.boar.deploy.entity.PackRecord;
import com.boarsoft.boar.deploy.event.EventParserBiz;
import com.boarsoft.boar.deploy.plan.PlanBiz;
import com.boarsoft.boar.deploy.plan.PlanItemBiz;
import com.boarsoft.boar.deploy.record.DeployRecordBiz;
import com.boarsoft.boar.deploy.record.PackRecordBiz;
import com.boarsoft.boar.deploy.websocket.CompileEventMSG;
import com.boarsoft.boar.deploy.websocket.CompileURLEvent;
import com.boarsoft.boar.deploy.websocket.DeployEventMSG;
import com.boarsoft.boar.deploy.websocket.DeployURLEvent;
import com.boarsoft.boar.deploy.websocket.ExportEventMSG;
import com.boarsoft.boar.job.BaseExportJob;
import com.boarsoft.boar.job.jenkins.JenkinsBroker;
import com.boarsoft.common.Util;
import com.boarsoft.common.util.HttpClientUtil;
import com.boarsoft.common.util.JsonUtil;
import com.boarsoft.flow.core.SimpleFlowEngine;
import com.boarsoft.web.websocket.WebsocketEndpoint;

/**
 * 处理JenKins每个子构建完成后的回调事件
 */

@Component("eventBiz")
public class EventParserBizImpl implements EventParserBiz {
	private static final Logger log = LoggerFactory.getLogger(EventParserBizImpl.class);

	@Autowired
	private PackRecordBiz packRecordBiz;
	@Autowired
	private DeployRecordBiz deployRecordBiz;
	@Autowired
	private PlanBiz planBiz;
	@Autowired
	private PlanItemBiz planItemBiz;
	@Autowired
	private SimpleFlowEngine flowEngine;

	@Override
	public void parseExportCallBack(HttpServletRequest req, BaseExportJob exportJob) {
		int jobCount = 0;
		String rs;
		CompileURLEvent eventRequest = null;
		Session session = null;
		try {
			rs = HttpClientUtil.readStr(req.getInputStream(), "UTF-8");
			log.info("Received export callback: {}", rs);
			if (rs != null && !"".equals(rs)) {
				eventRequest = JsonUtil.parseObject(rs, CompileURLEvent.class);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}

		Map<String, String[]> pm = req.getParameterMap();
		if (pm == null || pm.isEmpty()) {
			log.info("回调参数map为空！");
			return;
		}
		Set<String> keySets = pm.keySet();
		Iterator<String> is = keySets.iterator();
		String id = null, subId = null, exportType = null, exportStep = null, status = null, targetId = null, env = null,
				sessionId = null;

		while (is.hasNext()) {
			String key = is.next();
			String values[] = (String[]) pm.get(key);
			for (String value : values) {
				System.out.println("key=" + key + ",value=" + value);
				if ("exportStep".equals(key)) {
					exportStep = value;
				} else if ("exportType".equals(key)) {
					exportType = value;
				} else if ("env".equals(key)) {
					env = value;
				} else if ("id".equals(key)) {// 获取构建id
					id = value;
					sessionId = (String) BuildContext.getSessionId(id);
					session = WebsocketEndpoint.getSession(sessionId);
				} else if ("status".equals(key)) {
					status = value;
				} else if ("subId".equals(key)) {
					subId = value;
				} else if ("targetId".equals(key)) {
					targetId = value;
				}
			}
		}
		// 收到回调后维护pack_record表stage、status、lastTime字段
		PackRecord packRecord = packRecordBiz.get(id);
		if (packRecord == null) {
			log.info("No matched pack record found, id = {}", id);
			return;
		}
		packRecord.setStage(exportStep);
		packRecord.setStatus(status);
		packRecord.setEndTime(Util.getStdmfDateTime());
		packRecord.setLastUpdateTime(Util.getStdmfDateTime());
		packRecordBiz.save(packRecord);

		// 继续执行job条件:任意阶段失败，或者，最后一个阶段成功
		if (!"0".equals(status) || ("2".equals(exportStep) && "0".equals(status))) {
//			Map<String, Map<String, String>> jobs = BuildHandler.getJobStatus();
//			Map<String, String> jobStatus = jobs.get(sessionId);
//			jobCount = jobStatus.size();
//			// 一个job编译打包终态（成功或失败）时维护build_plan_detail表buildType，lastUpdateTime，status字段
//			String itemId = packRecord.getDetailId();
//			BuildPlanItem detail = buildPlanBiz.getPlanDetail(itemId);
//			detail.setBuildType(exportType);
//			detail.setLastUpdateTime(Util.getStdmfDateTime());
//			detail.setStatus(status);
//			buildPlanBiz.updateDetail(detail);
//			// 一个job编译打包终态（成功或失败）时维护build_plan_detail表buildType，lastUpdateTime，status字段////////
//			buildHandler.startCompileJobByDeployId(id, exportJob);// 调用方法继续执行job
		}

		ExportEventMSG exportMsg = new ExportEventMSG(jobCount, id, targetId, status, exportType, Integer.valueOf(exportStep));
		exportMsg.setEnv(env);
		WebsocketEndpoint.send(exportMsg, sessionId);// 向前端实时发送导源码进度信息

		if (eventRequest == null) {
			log.info("JenKins导出源码回调eventRequest为空！");
			return;
		}
		String phase = eventRequest.getBuild().getPhase(), stat = eventRequest.getBuild().getStatus(),
				jobId = eventRequest.getBuild().getParameters().getJob_id();
		sessionId = BuildContext.getSessionId(jobId);
		session = WebsocketEndpoint.getSession(sessionId);
		if ("FINALIZED".equals(phase) && "FAILURE".equals(stat)) {
			ExportEventMSG m = new ExportEventMSG(jobCount, "", "", "1", "", Integer.valueOf("0") + 1);
			WebsocketEndpoint.send(m, sessionId);
			log.info(JSON.toJSONString("JenKins遇到异常退出"));
		}
	}

	/**
	 * 解析【编译】回调参数 把post请求参数拆开分别解析
	 */
	@Override
	public void parseCompileCallBack(HttpServletRequest req, BaseExportJob exportJob) {
		String sessionId = null;
		CompileURLEvent eventRequest = null;
		try {
			String rs = HttpClientUtil.readStr(req.getInputStream(), "UTF-8");
			log.info("Received compile callback: {}", rs);
			if (Util.strIsNotEmpty(rs)) {
				eventRequest = JsonUtil.parseObject(rs, CompileURLEvent.class);
			}
		} catch (IOException e) {
			log.error("Error on parseCompileCallBack", e);
		}

		Map<String, String[]> pm = req.getParameterMap();
		String id = null, subId = null, compileType = null, compileStep = null, status = null, targetId = null, env = null,
				end = null;
		if (pm == null || pm.isEmpty()) {
			log.info("Parameters are missing");
			return;
		}
		Set<String> keySets = pm.keySet();
		Iterator<String> is = keySets.iterator();

		while (is.hasNext()) {
			String key = is.next();
			String values[] = (String[]) pm.get(key);
			for (String value : values) {
				System.out.println("key=" + key + ",value=" + value);

				if ("compileStep".equals(key)) {
					compileStep = value;
				} else if ("compileType".equals(key)) {
					compileType = value;
				} else if ("end".equals(key)) {
					end = value;
				} else if ("env".equals(key)) {
					env = value;
				} else if ("id".equals(key)) {// 获取构建id
					id = value;
					sessionId = (String) BuildContext.getSessionId(id);
				} else if ("status".equals(key)) {
					status = value;
				} else if ("subId".equals(key)) {
					subId = value;
				} else if ("targetId".equals(key)) {
					targetId = value;
				}
			}
		}

		// 收到回调后维护pack_record表stage、status、lastTime
		PackRecord packRecord = packRecordBiz.get(id);
		if (packRecord == null) {
			log.info("No matched pack record found, id = {}", id);
			return;
		}
		packRecord.setStage(compileStep);
		packRecord.setStatus(status);
		packRecord.setEndTime(Util.getStdmfDateTime());
		packRecord.setLastUpdateTime(Util.getStdmfDateTime());
		packRecordBiz.save(packRecord);

		// 继续执行job条件:任意阶段失败，或者，最后一个阶段成功
		boolean ret1 = !"0".equals(status), ret2 = ("true".equals(end) && "0".equals(status));
		if (ret1 || ret2) {
			// 一个job编译打包终态（成功或失败）时维护build_plan_detail表buildType，lastUpdateTime，status字段
//			String itemId = packRecord.getDetailId();
//			BuildPlanItem detail = buildPlanBiz.getPlanDetail(itemId);
//			detail.setBuildType(compileType);
//			detail.setLastUpdateTime(Util.getStdmfDateTime());
//			detail.setStatus(status);
//			buildPlanBiz.updateDetail(detail);
			// 一个job编译打包终态（成功或失败）时维护build_plan_detail表buildType，lastUpdateTime，status字段////////
//			buildHandler.startCompileJobByDeployId(id, exportJob);// 调用方法继续执行job
		}

		CompileEventMSG compileMsg = new CompileEventMSG(id, targetId, status, compileType, Integer.valueOf(compileStep));
		compileMsg.setEnv(env);// 根据环境信息更新对应的tab页面进度（重要）
		WebsocketEndpoint.send(compileMsg, sessionId);// 向前端实时发送编译进度信息

		if (eventRequest == null) {
			log.info("JenKins编译打包回调正常结束！");
			return;
		}
		String phase = eventRequest.getBuild().getPhase(), stat = eventRequest.getBuild().getStatus(),
				jobId = eventRequest.getBuild().getParameters().getJob_id();
//		String sessionId = (String) BuildContext.getSessionMap().get(jobId);
//		if ("FINALIZED".equals(phase) && "FAILURE".equals(stat)) {
//			CompileEventMSG m = new CompileEventMSG("", "", "1", "", Integer.valueOf("0") + 1);
//			Msg.setEnv(env);
//			WebsocketEndpoint.send(m, sessionId);// 向前端实时发送编译进度信息
//		}
	}

	/**
	 * 接收部署回调
	 */
	@Override
	public void parseDeployCallBack(HttpServletRequest req) {
		DeployURLEvent eventRequest = null;
		Session session = null;
		try {
			String rs = HttpClientUtil.readStr(req.getInputStream(), "UTF-8");
			if (rs != null && !"".equals(rs)) {
				log.info("部署回调请求体=" + JSON.toJSONString(rs));
				eventRequest = JsonUtil.parseObject(rs, DeployURLEvent.class);
				log.info(JSON.toJSONString(eventRequest));
			}

		} catch (IOException e) {
			e.printStackTrace();
		}
		Map<String, String[]> pm = req.getParameterMap();
		String id = null, subId = null, deployType = null, deployStep = null, status = null, targetId = null, env = null,
				IP = null, end = null, sessionId = null;

		if (pm == null || pm.isEmpty()) {
			log.info("回调参数map为空！");
			return;
		}
		// System.out.println("部署回调：");
		Set<String> keySets = pm.keySet();
		Iterator<String> is = keySets.iterator();
		while (is.hasNext()) {
			String key = is.next();
			String values[] = (String[]) pm.get(key);
			for (String value : values) {
				log.info("key=" + key + ",value=" + value);
				if ("deployStep".equals(key)) {
					deployStep = value;
				} else if ("deployType".equals(key)) {
					deployType = value;
				} else if ("end".equals(key)) {
					end = value;
				} else if ("env".equals(key)) {
					env = value;
				} else if ("id".equals(key)) {// 获取构建id
					id = value;
					sessionId = BuildContext.getSessionId(id);
					session = WebsocketEndpoint.getSession(sessionId);
				} else if ("IP".equals(key)) {// 获取构建id
					IP = value;
				} else if ("status".equals(key)) {
					status = value;
				} else if ("subId".equals(key)) {
					subId = value;
				} else if ("targetId".equals(key)) {
					targetId = value;
				}
			}

		}
		// ============收到回调后维护deploy_record表stage、status、lastUpdateTime字段【开始】==============
		DeployRecord deployRecord = deployRecordBiz.get(id + "$" + subId);
		if (deployRecord == null) {
			deployRecord = deployRecordBiz.get(id);
			if (deployRecord == null) {
				log.info(JSON.toJSONString("BBB根据父id：" + id) + "查询deployRecord返回空!不保存此次操作记录！");
			} else {
				deployRecord.setStage(deployStep);
				deployRecord.setDeployType(deployType);
				deployRecord.setStatus(status);
				deployRecord.setEndTime(Util.getStdmfDateTime());
				deployRecord.setLastUpdateTime(Util.getStdmfDateTime());
				log.info(JSON.toJSONString("第三次维护deployRecord"));
				deployRecordBiz.save(deployRecord);
			}
		}

		// ============收到回调后维护deploy_record表stage、status、lastUpdateTime字段【结束】==============

		// 回调jenkins条件:任意阶段失败，或者，最后一个阶段成功
		boolean ret1 = !"0".equals(status), ret2 = ("true".equals(end) && "0".equals(status));
		if (ret1 || ret2) {
			/// 一个job部署终态（成功或失败）时维护build_plan_detail表buildType，lastUpdateTime，status字段
			if (deployRecord != null) {
				String itemId = deployRecord.getDetailId();
				BuildPlanItem item = planItemBiz.get(itemId);
//				item.setBuildType(deployType);
				item.setLastTime(Util.getStdmfDateTime());
//				item.setStatus(status);
				planItemBiz.update(item);
			}
			/// 一个job部署终态（成功或失败）时维护build_plan_detail表buildType，lastUpdateTime，status字段////////
			jenKinsBrokerCallBack(sessionId, id, subId, status);// 回调JenkinsBroker
		}
		DeployEventMSG deployMsg = new DeployEventMSG(id, targetId, status, deployType, Integer.valueOf(deployStep));
		deployMsg.setEnv(env);
		deployMsg.setIp(IP);
		WebsocketEndpoint.send(deployMsg, sessionId);// 向前端实时发送部署进度信息

		if (eventRequest == null) {
			log.info("JenKins部署回调正常结束！");
			return;
		}
		String phase = eventRequest.getBuild().getPhase(), stat = eventRequest.getBuild().getStatus(),
				jobId = eventRequest.getBuild().getParameters().getJob_id();
		id = jobId;
		subId = eventRequest.getBuild().getParameters().getBuild_index();
//		sessionId = (String) BuildContext.getSessionMap().get(jobId);
		if ("FINALIZED".equals(phase) && "FAILURE".equals(stat)) {
			DeployEventMSG m = new DeployEventMSG("", "", "1", "", Integer.valueOf("0") + 1);
			m.setEnv(env);
			WebsocketEndpoint.send(m, sessionId);// 向前端实时发送编译进度信息
			// job失败仍然要回调jenkins，回调送状态2
			jenKinsBrokerCallBack(sessionId, id, subId, "2");// 构建异常结束后回调JenkinsBroker
		}
	}

	/**
	 * 构建完成回调JenkinsBroker方法
	 */
	@SuppressWarnings("unchecked")
	private void jenKinsBrokerCallBack(String sessionId, String id, String subId, String status) {
		if (Util.strIsEmpty(id)) {
			log.info(JSON.toJSONString("JenKins遇到异常后没返回构建Id！"));
			return;
		}
		JenkinsBroker broker = JenkinsBroker.getInstancesMap().get(id);
		if (broker == null) {
			log.info(JSON.toJSONString("根据构建Id获取JenkinsBroker实例错误！"));
			return;
		}
		try {
			int index = Integer.valueOf(subId);
			broker.onJobCompleted(id, index, status);// 此步骤中会维护broker属性，维护完成后放回map
			// 重新从map中获取broker
			broker = JenkinsBroker.getInstancesMap().get(id);
			int successfulJobs = broker.getCompletedJobCount(), failedJobs = broker.getFailedJobCount(),
					totalJobs = broker.getSubJobList().size();
			if (successfulJobs + failedJobs < totalJobs) {
				// job中子job还未完成，等待下一个job的回调
				log.info("job中子job还未完成，等待下一个job的回调");
				return;
			}
			log.info(JSON.toJSONString("job全部完成：成功：" + successfulJobs + ",失败：" + failedJobs));
			// 通过sessionId获取之前保存的flowId的map
//			Map<String, String> flowIdMap = BuildContext.getFlowInfo().get(sessionId);
//			String flow_ID = flowIdMap.get(BuildKey.FLOW_ID), ID = flowIdMap.get(BuildKey.ID);
//			log.info("flow_ID ={},ID={}", flow_ID, ID);
//			SimpleFlow flow = BuildContext.getBuild(flowId);
//			Map<String, Object> flowData = (Map<String, Object>) flow.getData();
//			if (failedJobs > 0) {// 有失败的job
//				// TODO resume flow时传递结果：true or false
//				flowData.put(BuildKey.RESULT, false);
//			} else {
//				flowData.put(BuildKey.RESULT, true);
//			}
//			flow.setData(flowData);
//			flowEngine.resume(flow);
			JenkinsBroker.getInstancesMap().remove(id);// 移除map中的jenkinsBroker
//			buildHandler.startDeployJobByDeployId(id);// 调用方法继续执行job
		} catch (Throwable e) {
			log.error("Error on process jenkins callback", e);
		}
	}
}